﻿Imports Amazon.S3
Imports Amazon.S3.Model


Public Class CAmazonS3

    Public Delegate Sub DLoaded1000(total As Integer)

    Public Shared Function Buckets(client As AmazonS3Client) As List(Of S3Bucket)
        Return client.ListBuckets().Buckets
    End Function

    Public Shared Sub CreateBucket(client As AmazonS3Client, bucketName As String)
        Dim req As New PutBucketRequest()
        req.BucketName = bucketName
        req.BucketRegion = S3Region.APS1
        Dim resp As PutBucketResponse = client.PutBucket(req)
    End Sub



    Public Shared Function Objects(client As AmazonS3Client, bucket As String, notify As DLoaded1000) As List(Of S3Object)
        Dim list As New List(Of S3Object)

        Dim req As New ListObjectsRequest()
        req.BucketName = bucket

        Dim resp As ListObjectsResponse = client.ListObjects(req) 'Gets 1000 at a time
        list.AddRange(resp.S3Objects)
        notify.Invoke(list.Count)
        While resp.IsTruncated
            req.Marker = resp.NextMarker
            resp = client.ListObjects(req)
            list.AddRange(resp.S3Objects)
            If Not IsNothing(notify) Then notify.Invoke(list.Count)
        End While
        Return list
    End Function

    Public Shared Function PutObject(client As AmazonS3Client, bucket As String, filePath As String, key As String) As String
        If New System.IO.FileInfo(filePath).Length > 4000000 Then
            Return PutLargeObject(client, bucket, filePath, key) 'No metadata for large objects
        End If


        Dim req As New PutObjectRequest
        req.BucketName = bucket
        req.FilePath = filePath
        req.Key = key
        req.Timeout = New TimeSpan(1, 0, 0)

        req.Metadata.Add("MACHINENAME", My.Computer.Name)
        req.Metadata.Add("USERNAME", Environment.UserName)
        req.Metadata.Add("CREATIONTIME", System.IO.File.GetCreationTime(filePath).ToString("dd MMM yyyy hh:mm:ss tt")) 'Readable but unambiguous
        req.Metadata.Add("LASTMODIFIED", System.IO.File.GetLastWriteTime(filePath).ToString("dd MMM yyyy hh:mm:ss tt")) 'Readable but unambiguous

        'Used to check md5
        Dim response As PutObjectResponse = client.PutObject(req)
        Return response.ETag



        'TODO: Multipart uploads for large files
        'Dim r As New InitiateMultipartUploadRequest()
        'r.BucketName = bucket
        'client.InitiateMultipartUpload(Nothing)
        'client.ListParts(Nothing)
        'client.AbortMultipartUpload(Nothing)
        'client.CompleteMultipartUpload(Nothing)
    End Function
    Private Shared Function PutLargeObject(client As AmazonS3Client, bucket As String, filePath As String, key As String)
        Dim config As New Transfer.TransferUtilityConfig
        config.DefaultTimeout = New TimeSpan(6, 0, 0)
        config.MinSizeBeforePartUpload = 4000000
        config.ConcurrentServiceRequests = 3
        'Defaults: 5mins, 16mb, 10 threads

        Dim tu As New Transfer.TransferUtility(client, config)
        tu.Upload(filePath, bucket, key)
        Return String.Empty


        'Dim metaInfo As New Specialized.NameValueCollection(3)
        'metaInfo.Add("MACHINENAME", My.Computer.Name)
        'metaInfo.Add("USERNAME", Environment.UserName)
        'metaInfo.Add("CREATIONTIME", IO.File.GetCreationTime(filePath).ToString("dd MMM yyyy hh:mm:ss tt")) 'Readable but unambiguous
        'metaInfo.Add("LASTMODIFIED", IO.File.GetLastWriteTime(filePath).ToString("dd MMM yyyy hh:mm:ss tt")) 'Readable but unambiguous

        'Dim req As New PutObjectRequest
        'req.BucketName = bucket
        'req.Key = key.Replace("\", "/")
        'req.AddHeader("x-amz-metadata-directive", "REPLACE")
        'Dim resp As PutObjectResponse = client..PutObject(req.WithMetaData(metaInfo))



        'Dim req As New InitiateMultipartUploadRequest()
        'req.BucketName = bucket

        'Dim response As InitiateMultipartUploadResponse = client.InitiateMultipartUpload(req)
        'Dim uploadId As String = response.UploadId
        'client.ListParts(Nothing)
        'client.AbortMultipartUpload(Nothing)
        'client.CompleteMultipartUpload(Nothing)
    End Function

    Public Shared Sub GetObject(client As AmazonS3Client, bucket As String, key As String, filePath As String)
        Dim req As New GetObjectRequest
        req.BucketName = bucket
        req.Key = key.Replace("\", "/")
        Dim resp As GetObjectResponse = client.GetObject(req)
        resp.WriteResponseStreamToFile(filePath, False)

        Try
            Dim s As String = resp.Metadata("LASTMODIFIED")
            If String.IsNullOrEmpty(s) Then s = resp.Metadata("x-amz-meta-lastmodified")
            If String.IsNullOrEmpty(s) Then Exit Sub 'No metadata

            Dim dd As DateTime
            Try
                dd = DateTime.Parse(s)
            Catch ex As Exception
                Dim ss As String() = s.Split("/")
                s = String.Concat(ss(1), "/", ss(0), "/", ss(2))
                dd = DateTime.Parse(s)
            End Try

            Dim ct As DateTime = dd
            s = resp.Metadata("CREATIONTIME")
            If Not String.IsNullOrEmpty(s) Then ct = DateTime.Parse(s)
            System.IO.File.SetCreationTime(filePath, ct)
            System.IO.File.SetLastWriteTime(filePath, dd)
        Catch 'Suppress any metadata errors except in debug (should parse the dates ok)
        End Try
    End Sub

    'Public Shared Function GetVersioning(amazon As AmazonS3Client, bucket As String) As S3BucketVersioningConfig
    '    Dim req As New GetBucketVersioningRequest()
    '    req.BucketName = bucket
    '    Dim response As GetBucketVersioningResponse = amazon.GetBucketVersioning(req)
    '    Return response.VersioningConfig
    'End Function


End Class
